{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.13.3'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "arr = np.array(\n",
    "[\n",
    "    [1,8,3],\n",
    "    [4,5,6]\n",
    "])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## read \"axis=0\" as \"across rows\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 5, 13,  9])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum(axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## \"axis=1\" means \"across columns\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([12, 15])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum(axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## :: (double colon) reverses an array across the first (0-th) axis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4, 5, 6],\n",
       "       [1, 8, 3]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4, 5, 6],\n",
       "       [1, 8, 3]])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# this is equivalent to:\n",
    "np.flip(arr,axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 2, 1],\n",
       "       [0, 1, 2]])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "orders = np.argsort(arr)\n",
    "orders"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_elems = orders[:,:1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1],\n",
       "        [1]],\n",
       "\n",
       "       [[4],\n",
       "        [4]]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[:,first_elems]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## original implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def ranking_precision_score(y_true, y_score, k=None):\n",
    "    \"\"\"Precision at rank k\n",
    "    Parameters\n",
    "    ----------\n",
    "    y_true : array-like, shape = [n_samples]\n",
    "        Ground truth (true relevance labels).\n",
    "    y_score : array-like, shape = [n_samples]\n",
    "        Predicted scores.\n",
    "    k : int\n",
    "        Rank.\n",
    "    Returns\n",
    "    -------\n",
    "    precision @k : float\n",
    "    \"\"\"\n",
    "    if k is None:\n",
    "        k = 10\n",
    "\n",
    "    unique_y = np.unique(y_true)\n",
    "\n",
    "    if len(unique_y) > 2:\n",
    "        raise ValueError(\"Only supported for two relevance levels.\")\n",
    "\n",
    "    pos_label = unique_y[1]\n",
    "    n_pos = np.sum(y_true == pos_label)\n",
    "\n",
    "    order = np.argsort(y_score)[::-1]\n",
    "    y_true = np.take(y_true, order[:k])\n",
    "    n_relevant = np.sum(y_true == pos_label)\n",
    "\n",
    "    # Divide by min(n_pos, k) such that the best achievable score is always 1.0.\n",
    "    return float(n_relevant) / min(n_pos, k)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## my implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "def precision_at_k(y_true, y_preds, k=None):\n",
    "    \"\"\"Precision at rank k\n",
    "    Parameters\n",
    "    ----------\n",
    "    y_true : array-like, shape = [n_samples,n_labels]\n",
    "        Ground truth (binary) (true relevance labels)\n",
    "    y_preds : array-like, shape = [n_samples,n_labels]\n",
    "        Predicted scores (float) (label probabilities)\n",
    "    k : int\n",
    "        Rank.\n",
    "    Returns\n",
    "    -------\n",
    "    precision @k : float\n",
    "    \"\"\"\n",
    "    if k is None:\n",
    "        k = 10\n",
    "\n",
    "    assert y_true.shape == y_preds.shape, \"Y_true (binary label vectors) and y_preds (predicted probability scores) must have the same shapes.\"\n",
    "\n",
    "    unique_y = np.unique(y_true)\n",
    "\n",
    "    if len(unique_y) > 2:\n",
    "        raise ValueError(\"Only supported for two relevance levels (binary \" +\n",
    "                         \"indicator arrays).\")\n",
    "\n",
    "    positive_label = unique_y[1]\n",
    "    n_positives = np.sum(y_true == positive_label)\n",
    "\n",
    "    order = np.argsort(y_preds)[::-1]\n",
    "\n",
    "    y_true = np.take(y_true, order[:k])\n",
    "\n",
    "    n_relevant = np.sum(y_true == positive_label)\n",
    "\n",
    "    # Divide by min(n_pos, k) such that the best achievable score is always 1.0.\n",
    "    return float(n_relevant) / min(n_positives, k)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## precision at k\n",
    "\n",
    "for this example, P@2 should equal 0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_trues = np.array([\n",
    "    [1,0,0,1],\n",
    "    [0,0,1,1]\n",
    "])\n",
    "\n",
    "y_preds = np.array([\n",
    "    [0.25,0.3,0.2,0.35],\n",
    "    [0.2,0.1,0.4,0.3]\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.5, 1.0)"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score0=ranking_precision_score(y_trues[0], y_preds[0],2)\n",
    "score1=ranking_precision_score(y_trues[1], y_preds[1],2)\n",
    "score0,score1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "precision_at_k(y_trues,y_preds,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Global TF Kernel (Python 3)",
   "language": "python",
   "name": "global-tf-python-3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
